/**
 * Copyright (c) 2023 myons Inc. All rights reserved.
 */
package cn.zmwh.im.server.exception;

import cn.hutool.core.util.StrUtil;
import cn.zmwh.im.server.api.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局异常处理
 *
 * @author dm
 * @since 2020/2/27.
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private HttpServletRequest request;

    @ExceptionHandler(value = RRException.class)
    public Result handle(RRException e) {
        // 打印堆栈信息
        String stackTrace = ThrowableUtil.getStackTrace(e);
        log.error(stackTrace);
        if (e.getStatus() != null) {
            return Result.failed(e.getStatus(), e.getMessage());
        }
        if (StrUtil.isBlank(e.getMessage())
//                ||NullPointerException.class.isInstance(e)
        ) {
            sendMsg("handle_null_pointer_exception:", stackTrace);
            return Result.failed("请联系客服人员," + stackTrace);
        }
        return Result.failed(HttpStatus.PRECONDITION_FAILED.value(), e.getMessage());
    }

    @ExceptionHandler(value = NullPointerException.class)
    public Result handleNullPointerException(NullPointerException e) {
        String stackTrace = ThrowableUtil.getStackTrace(e);
        sendMsg("handle_null_pointer_exception:", stackTrace);
        log.error(stackTrace);
        return Result.failed("请联系客服人员," + stackTrace);
    }

    /**
     * 处理404异常
     *
     * @param e NoHandlerFoundException
     * @return
     */
//    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<Result> noHandlerFoundException(HttpServletRequest req, Exception e) {
        sendMsg("noHandlerFoundException", "接口路径错误");
        log.error("404异常 NoHandlerFoundException, method = {}, path = {} ", req.getMethod(), req.getServletPath(), e);
        return ResponseEntity.status(HttpStatus.NOT_FOUND.value()).body(Result.failed(HttpStatus.NOT_FOUND.value(), "未找到您请求的资源。"));
    }

    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public Result handle(HttpRequestMethodNotSupportedException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return Result.failed(HttpStatus.METHOD_NOT_ALLOWED.value(), "请求方式错误！");
    }
//
//    @ExceptionHandler(value = DataAccessException.class)
//    public Result handleDataAccessException(DataAccessException e) {
//        // 打印堆栈信息
//        String stackTrace = ThrowableUtil.getStackTrace(e);
//        String msg = "数据库访问异常:" + stackTrace;
//        log.error(msg);
//        sendMsg("handle_dataAccess_exception:",stackTrace);
//        return Result.failed("请联系客服人员," +  msg);
//    }
//
//    @ExceptionHandler(value = QueryTimeoutException.class)
//    public Result handleQueryTimeoutException(QueryTimeoutException e) {
//        // 打印堆栈信息
//        String stackTrace = ThrowableUtil.getStackTrace(e);
//        String msg = "数据库访问超时:" + stackTrace;
//        log.error(msg);
//        return Result.failed("请联系客服人员," +  msg);
//    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handleValidException(MethodArgumentNotValidException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField() + fieldError.getDefaultMessage();
            }
        }
        return Result.validateFailed(message);
    }

    @ExceptionHandler(value = BindException.class)
    public Result handleValidException(BindException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField() + fieldError.getDefaultMessage();
            }
        }
        return Result.validateFailed(message);
    }


    /**
     * 处理所有不可知的异常
     */
    @ExceptionHandler(Throwable.class)
    public Result handleException(Throwable e) {
        // 打印堆栈信息
        String stackTrace = ThrowableUtil.getStackTrace(e);
        log.error(stackTrace);
        sendMsg("handle_exception:", stackTrace);
        return Result.failed("请联系客服人员," + stackTrace);
    }

    private void sendMsg(String key, String msg) {
//        if (!redisUtils.hasKey(key)) {
//            String requestURI = "接口路径：";
//            try {
//                requestURI = requestURI + request.getRequestURI() + "\n";
//            } catch (Exception item) {
//                log.error("获取uri异常", item);
//                requestURI = requestURI + "异常无法获取到";
//            }
//            ddSender.sendError(active + "未捕获异常", requestURI + msg, null, false);//10分钟发一次防止钉钉消息被占用光
//            redisUtils.incr(key, 1);
//            redisUtils.expireTimeUnit(key, 10, TimeUnit.MINUTES);
//        } else {
//            redisUtils.incr(key, 1);
//        }
    }
}
